package gui;

import gui.components.ChatPanel;
import gui.components.ClientListPanel;
import gui.components.MainMenuBar;
import gui.components.WhiteboardCanvas;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Observable;
import java.util.Observer;

import javax.swing.AbstractButton;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JToggleButton;
import javax.swing.WindowConstants;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import network.client.WhiteboardClient;
import controller.ButtonController;
import controller.DrawingController;
import controller.UserListController;
import data.DrawingSettings;
import data.ShapesData;
import data.WorkingMode;
import data.WorkingMode.MODE;

/**
 * The main user interface for this application
 * @author Jie Zhao(28865)
 * 
 */
public class WhiteBoard extends JFrame implements Observer{

	private ButtonGroup buttonGroup = new ButtonGroup();
	private final WhiteboardCanvas canvas = new WhiteboardCanvas();
	private final MainMenuBar menuBar = new MainMenuBar(this,canvas);

	private final JPanel panel = new JPanel();
	private final ClientListPanel userListPanel = new ClientListPanel();

	private final JPanel shapesPanel = new JPanel();
	private final JPanel panel_4 = new JPanel();
	private final JPanel colorSettingPanel = new JPanel();
	private final JTabbedPane tabbedPane = new JTabbedPane();
	private final JPanel basicShapes = new JPanel();
	private final JPanel basicShapePanel = new JPanel();
	private final JToggleButton lineToggleButton = new JToggleButton();
	
	private final JToggleButton ovalToggleButton = new JToggleButton();
	private final JToggleButton rectangleToggleButton = new JToggleButton();
	private final JToggleButton circleToggleButton = new JToggleButton();
	private final JToggleButton triangleToggleButton = new JToggleButton();
	private final JToggleButton starToggleButton = new JToggleButton();
	private final JToggleButton textToggleButton = new JToggleButton();
	private final JToggleButton freePenToggleButton = new JToggleButton();
	private final JToggleButton eraserToggleButton = new JToggleButton();
	private final JToggleButton polygonToggleButton = new JToggleButton();
	private final JButton clearButton = new JButton();

	private final JLabel strokeLabel = new JLabel();
	private final JButton lineColor = new JButton();
	private final JLabel filledColorLabel = new JLabel();
	private final JButton filledColor = new JButton();
	private final JLabel filledLabel = new JLabel();
	private final JCheckBox filledCheckBox = new JCheckBox();
	private final JLabel strokeSizeLabel = new JLabel();
	private final JPanel canvasPanel = new JPanel();

	private final JSlider strokeSize = new JSlider();
	private final JLabel eraserSizeLabel = new JLabel();
	private final JSlider eraserSize = new JSlider();
	private final JPanel chatPanel = new ChatPanel();

	private final DrawingSettings drawingSettings = DrawingSettings
			.getInstance();
	private final DrawingController drawingController = DrawingController
			.getInstance();

	private final UserListController clientListController = UserListController
			.getInstance();

	private WorkingMode wm = WorkingMode.getInstance();
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new WhiteBoard().setVisible(true);
	}
@Override
public void update(Observable o, Object arg) {
	switch (WorkingMode.getInstance().getWorkingMode()) {
	case CLIENT:
		clearButton.setEnabled(false);
		break;
	case LOCAL:
		clearButton.setEnabled(true);
		ShapesData.getInstance().clear();
		drawingController.clear();
		break;
	case SERVER:
		clearButton.setEnabled(true);
		break;
	default:
		break;
	}
	
}
	public WhiteBoard() {
		super();
		try {
			jbInit();
			WorkingMode.getInstance().addObserver(this);
			drawingController.setCanvas(canvas);
			wm.changeWorkingMode(MODE.LOCAL);
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}

	private void jbInit() throws Exception {
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		addWindowListener(new ThisWindowListener());
		getContentPane().setLayout(new BorderLayout());
		setSize(905, 600);
		setJMenuBar(menuBar);

		setTitle("Whiteboard Client");


		canvas.setName("canvas");
		canvas.setBackground(Color.WHITE);

		getContentPane().add(panel, BorderLayout.WEST);
		panel.setPreferredSize(new Dimension(220, 400));
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		shapesPanel.setName("shapesPanel");
		shapesPanel.setPreferredSize(new Dimension(220, 300));
		shapesPanel.setLayout(new BorderLayout());
		panel.add(shapesPanel);
		shapesPanel.setBorder(new TitledBorder(null, "Shapes",
				TitledBorder.DEFAULT_JUSTIFICATION,
				TitledBorder.DEFAULT_POSITION, null, null));

		shapesPanel.add(tabbedPane);

		tabbedPane.addTab("Basic", null, basicShapes, null);
		final FlowLayout flowLayout = new FlowLayout();
		flowLayout.setHgap(2);
		flowLayout.setVgap(2);
		flowLayout.setAlignment(FlowLayout.LEFT);
		basicShapes.setLayout(flowLayout);

		basicShapes.add(basicShapePanel);
		final GridLayout gridLayout = new GridLayout(0, 2);
		gridLayout.setVgap(5);
		gridLayout.setHgap(5);
		basicShapePanel.setLayout(gridLayout);

		basicShapePanel.add(lineToggleButton);
		lineToggleButton.setActionCommand("draw_line");
		lineToggleButton.setName("Line");
		lineToggleButton.setSelected(true);
		buttonGroup.add(lineToggleButton);
		lineToggleButton.setText("Line");

		basicShapePanel.add(rectangleToggleButton);
		rectangleToggleButton.setActionCommand("draw_rectangle");
		rectangleToggleButton.setName("Rectangle");
		buttonGroup.add(rectangleToggleButton);
		rectangleToggleButton.setText("Rectangle");

		basicShapePanel.add(ovalToggleButton);
		ovalToggleButton.setActionCommand("draw_oval");
		ovalToggleButton.setName("Oval");
		buttonGroup.add(ovalToggleButton);
		ovalToggleButton.setText("Oval");

		basicShapePanel.add(this.circleToggleButton);
		circleToggleButton.setActionCommand("draw_circle");
		buttonGroup.add(circleToggleButton);
		circleToggleButton.setName("Circle");
		circleToggleButton.setText("Circle");

		basicShapePanel.add(triangleToggleButton);
		triangleToggleButton.setActionCommand("draw_triangle");
		triangleToggleButton.setName("Triangle");
		buttonGroup.add(triangleToggleButton);
		triangleToggleButton.setText("Triangle");

		basicShapePanel.add(starToggleButton);
		starToggleButton.setActionCommand("draw_star");
		starToggleButton.setName("Star");
		buttonGroup.add(starToggleButton);
		starToggleButton.setText("Star");

		basicShapePanel.add(textToggleButton);
		textToggleButton.setActionCommand("draw_text");
		textToggleButton.setName("Text");
		buttonGroup.add(textToggleButton);
		textToggleButton.setText("Text");

		basicShapePanel.add(freePenToggleButton);
		freePenToggleButton.setActionCommand("draw_freepen");
		freePenToggleButton.setName("FreePen");
		buttonGroup.add(freePenToggleButton);
		freePenToggleButton.setText("FreePen");

		basicShapePanel.add(eraserToggleButton);
		eraserToggleButton.setActionCommand("draw_eraser");
		eraserToggleButton.setName("Eraser");
		buttonGroup.add(eraserToggleButton);
		eraserToggleButton.setText("Eraser");

		basicShapePanel.add(polygonToggleButton);
		polygonToggleButton.setActionCommand("draw_polygon");
		buttonGroup.add(polygonToggleButton);
		polygonToggleButton.setName("Polygon");
		polygonToggleButton.setText("Polygon");

		basicShapePanel.add(clearButton);
		clearButton.addActionListener(new ClearButtonActionListener());
		clearButton.setActionCommand("clear");
		clearButton.setText("Clear");

		colorSettingPanel.setName("panel_5");
		final GridLayout gridLayout_1 = new GridLayout(0, 2);
		gridLayout_1.setVgap(5);
		colorSettingPanel.setLayout(gridLayout_1);
		panel.add(colorSettingPanel);
		colorSettingPanel.setBorder(new TitledBorder(null, "Color Setting",
				TitledBorder.DEFAULT_JUSTIFICATION,
				TitledBorder.DEFAULT_POSITION, null, null));

		colorSettingPanel.add(strokeLabel);
		strokeLabel.setText("Line Color:");

		colorSettingPanel.add(lineColor);
		lineColor.addActionListener(new LineColorActionListener());
		lineColor.setBorder(new BevelBorder(BevelBorder.RAISED, Color.WHITE,
				Color.WHITE));
		lineColor.setBackground(Color.BLACK);
		lineColor.setMargin(new Insets(2, 14, 2, 14));

		colorSettingPanel.add(filledColorLabel);
		filledColorLabel.setText("Filled Color:");

		colorSettingPanel.add(filledColor);
		filledColor.addActionListener(new FilledColorActionListener());
		filledColor.setBorder(new BevelBorder(BevelBorder.RAISED, Color.BLACK,
				Color.BLACK));
		filledColor.setBackground(Color.WHITE);
		filledColor.setAutoscrolls(true);

		colorSettingPanel.add(filledLabel);
		filledLabel.setText("Is Filled:");

		colorSettingPanel.add(filledCheckBox);
		filledCheckBox.addActionListener(new FilledCheckBoxActionListener());
		filledCheckBox.setText("Filled");
		panel_4.setName("panel_4");
		panel_4.setLayout(new GridLayout(0, 2));
		panel.add(panel_4);
		panel_4.setBorder(new TitledBorder(null, "Size Setting",
				TitledBorder.DEFAULT_JUSTIFICATION,
				TitledBorder.DEFAULT_POSITION, null, null));

		panel_4.add(strokeSizeLabel);
		strokeSizeLabel.setText("Stroke Size:");

		panel_4.add(strokeSize);
		strokeSize.addChangeListener(new StrokeSizeChangeListener());
		strokeSize.setMajorTickSpacing(10);
		strokeSize.setValue(1);
		strokeSize.setMinimum(1);

		panel_4.add(eraserSizeLabel);
		eraserSizeLabel.setText("Eraser Size:");

		panel_4.add(eraserSize);
		eraserSize.addChangeListener(new EraserSizeChangeListener());
		eraserSize.setMajorTickSpacing(10);
		eraserSize.setMinimum(1);

		getContentPane().add(chatPanel, BorderLayout.SOUTH);

		getContentPane().add(userListPanel, BorderLayout.EAST);

		

		Component[] buttons = basicShapePanel.getComponents();

		canvasPanel.setLayout(new BorderLayout());
		canvasPanel.add(canvas, BorderLayout.CENTER);
		getContentPane().add(canvasPanel, BorderLayout.CENTER);
		// Adding actionListener for all buttons
		for (Component button : buttons) {
			if (button.getClass().equals(JToggleButton.class)) {
				// System.out.println(button.getName());
				((AbstractButton) button).addActionListener(ButtonController
						.getInstance());
			}
		}

		drawingSettings.setFilled(filledCheckBox.isSelected());
		drawingSettings.setFilledColor(filledColor.getBackground());
		drawingSettings.setLineColor(lineColor.getBackground());
		drawingSettings.setStroke(new BasicStroke(strokeSize.getValue()));
		drawingSettings.setEraserSize(new BasicStroke(eraserSize.getValue()));
		clientListController.setUi(userListPanel);
	}

	private class StrokeSizeChangeListener implements ChangeListener {
		public void stateChanged(ChangeEvent e) {
			strokeSize_stateChanged(e);
		}
	}

	private class LineColorActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			lineColor_actionPerformed(e);
		}
	}

	private class FilledColorActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			filledColor_actionPerformed(e);
		}
	}

	private class FilledCheckBoxActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			filledCheckBox_actionPerformed(e);
		}
	}

	private class ClearButtonActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			clearButton_actionPerformed(e);
		}
	}

	private class EraserSizeChangeListener implements ChangeListener {
		public void stateChanged(ChangeEvent e) {
			eraserSize_stateChanged(e);
		}
	}





	private class ThisWindowListener extends WindowAdapter {
		public void windowClosing(WindowEvent e) {
			this_windowClosing(e);
		}
	}


	protected void strokeSize_stateChanged(ChangeEvent e) {
		if (!strokeSize.getValueIsAdjusting()) {
			drawingSettings.setStroke(new BasicStroke(strokeSize.getValue(),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
			drawingController.updateColorSetting();
		}

	}

	protected void lineColor_actionPerformed(ActionEvent e) {
		Color oldLineColor = lineColor.getBackground();
		Color newLineColor = JColorChooser.showDialog(null,
				"Choose a line Color:", oldLineColor);
		if (newLineColor != null) {
			drawingSettings.setLineColor(newLineColor);
			lineColor.setBackground(newLineColor);
			drawingController.updateColorSetting();
		}
	}

	protected void filledColor_actionPerformed(ActionEvent e) {
		Color oldFilledColor = filledColor.getBackground();
		Color newFilledColor = JColorChooser.showDialog(null,
				"Choose a line Color:", oldFilledColor);
		if (newFilledColor != null) {
			drawingSettings.setFilledColor(newFilledColor);
			filledColor.setBackground(newFilledColor);
			drawingController.updateColorSetting();
		}
	}

	protected void filledCheckBox_actionPerformed(ActionEvent e) {
		drawingSettings.setFilled(filledCheckBox.isSelected());
		drawingController.updateColorSetting();
	}

	protected void clearButton_actionPerformed(ActionEvent e) {
		drawingController.clear();
		canvas.repaint();
	}

	protected void eraserSize_stateChanged(ChangeEvent e) {
		if (!eraserSize.getValueIsAdjusting()) {
			drawingSettings
					.setEraserSize(new BasicStroke(eraserSize.getValue()));
			drawingController.updateColorSetting();
		}
	}

	WhiteboardClient whiteboardClient = null;



	protected void this_windowClosing(WindowEvent e) {
		try
		{
			System.out.println("Window closing, shutdown client.");
			whiteboardClient.close();
		}
		catch (Exception ee) {
			// TODO: handle exception
		}
	}


}
